<template>
    <div class="container">
        <div class="header">
            <div>{{termTitle}}</div>
            <el-button @click="openDrawer" icon="el-icon-folder-opened" type="primary" style="margin-right: 16px;">文件管理器
            </el-button>
        </div>
        <div class="terminal">
            <div ref="terminal"/>
        </div>
        <el-drawer
                title="文件管理器"
                :visible.sync="drawer"
                size="50%"
                placement="right"
                custom-class="drawerHead">
            <div class="drawerHeader">
                <el-breadcrumb separator="/">
                    <el-breadcrumb-item>
                        <el-link icon="el-icon-s-home" type="primary" @click="openJumpServerSftpLs('','0')"></el-link>
                    </el-breadcrumb-item>
                    <el-breadcrumb-item v-for="(item,index) in pwdCopy" :key="index"><span @click="openJumpServerSftpLs(item,'2')">{{item}}</span></el-breadcrumb-item>
                </el-breadcrumb>
                <div class="actions">
                    <span>显示隐藏文件：</span>
                    <el-switch
                            v-model="isHide"
                            active-color="#13ce66"
                            @change="changeFunction"
                            active-text="开启"
                            inactive-text="关闭">
                    </el-switch>
                    <el-upload
                        :action="`${uploadUrl}`"
                        :on-error="uploadError"
                        :on-success="uploadSuccess"
                        :show-file-list="false">
                        <el-button size="small" type="primary">上传文件</el-button>
                    </el-upload>
                </div>
            </div>
            <div class="table-file">
                <el-table :data="tableData"  row-key="name"  style="width: 96%;margin-left:2%" height="600">
                    <el-table-column prop="name"  label="名称"  align="center">
                        <template slot-scope="scope" >
                            <div>
                                <i v-if="scope.row.is_dir" class="el-icon-folder" style="color:#1890ff"></i>
                                <i v-else class="el-icon-document" ></i>
                                <span @click="openJumpServerSftpLs(scope.row.name,'1')" style="color: #1890ff;margin-left: 5px">{{scope.row.name}}</span>
                            </div>
                        </template>
                    </el-table-column>
                    <el-table-column label="大小" align="center" width="100">
                        <template slot-scope="scope">
                            <div v-if="!scope.row.is_dir">{{scope.row.size}}</div>
                        </template>
                    </el-table-column>
                    <el-table-column prop="time" label="修改时间" width="220" align="center"></el-table-column>
                    <el-table-column prop="mod" label="属性" width="150" align="center"></el-table-column>
                    <el-table-column prop="address" label="操作" width="100" align="center">
                        <template slot-scope="scope">
                            <el-link v-if="!scope.row.is_dir" class="el-icon-download" style="color:#1890ff;font-size: 20px;margin-right: 15px" @click="downLoadFile(scope.row.path,scope.row.name)"></el-link>
                        </template>
                    </el-table-column>
                </el-table>
            </div>

        </el-drawer>
    </div>
</template>

<script>
    import {
        getJumpServerSftpLs,
    }from "@/api/jump_server_sftp";
    import {
        getJumpServerUserById,
    }from "@/api/jump_server_user";
    import {Terminal} from "xterm";
    import * as fit from "xterm/lib/addons/fit/fit";
    import {Base64} from "js-base64";
    import * as webLinks from "xterm/lib/addons/webLinks/webLinks";
    import * as search from "xterm/lib/addons/search/search";
    import "xterm/dist/xterm.css"
    let bindTerminalResize = (term, websocket) => {
        let onTermResize = size => {
            websocket.send(
                JSON.stringify({
                    type: "resize",
                    rows: size.rows,
                    cols: size.cols,
                })
            );
        };
        // register resize event.
        term.on("resize", onTermResize);
        // unregister resize event when WebSocket closed.
        websocket.addEventListener("close", function () {
            term.off("resize", onTermResize);
        });
    };
    let bindTerminal = (term, websocket, bidirectional, bufferedTime) => {
        term.write('\r\nWelcome to Felix Web Ssh Terminal\n\r\n');
        term.socket = websocket;
        let messageBuffer = null;
        let handleWebSocketMessage = function (ev) {
            if (bufferedTime && bufferedTime > 0) {
                if (messageBuffer) {
                    messageBuffer += ev.data;
                } else {
                    messageBuffer = ev.data;
                    setTimeout(function () {
                        term.write(messageBuffer);
                    }, bufferedTime);
                }
            } else {
                term.write(ev.data);
            }
        };

        let handleTerminalData = function (data) {
            websocket.send(
                JSON.stringify({
                    type: "cmd",
                    cmd: Base64.encode(data) // encode data as base64 format
                })
            );
        };

        websocket.onmessage = handleWebSocketMessage;
        if (bidirectional) {
            term.on("data", handleTerminalData);
        }

        // send heartbeat package to avoid closing webSocket connection in some proxy environmental such as nginx.
        let heartBeatTimer = setInterval(function () {
            websocket.send(JSON.stringify({type: "heartbeat", data: ""}));
        }, 20 * 1000);

        websocket.addEventListener("close", function () {
            websocket.removeEventListener("message", handleWebSocketMessage);
            term.off("data", handleTerminalData);
            delete term.socket;
            clearInterval(heartBeatTimer);
        });
    };
    export default {
        name: "jumpServerWeb",
        data() {
            return {
                obj:{},
                localMessage: '',
                isFullScreen: false,
                searchKey: "",
                v: this.visible,
                ws: null,
                term: null,
                thisV: this.visible,
                drawer:false,
                tableData:[],
                pwd:[],
                pwdCopy: [],
                id:null,
                uuid:null,
                isHide:false,
                dirPath:null,
                tableDataHide: []
            };
        },
        watch: {
            visible(val) {
                this.v = val;//新增result的watch，监听变更并同步到myResult上
            }
        },
        computed: {
            termTitle() {
                if (this.obj) {
                    return `${this.obj.virtual_code}|${this.obj.ssh_user}@${this.obj.ssh_ip_address}:${this.obj.ssh_port}`
                }
                return ""
            },
            wsUrl() {
                let url = (location.protocol === "http:" ? "ws" : "wss") + "://" + location.hostname + ":8081" + "/jump/server/webWs";
                return `${url}?Id=${this.obj.ID}&cols=${this.term.cols}&rows=${this.term.rows}&uuid=${this.uuid}`
            },
            uploadUrl(){
                let url ="http://" + location.hostname + ":8081" + "/jump/sftp/upLoadJumServerSftpFile";
                return `${url}?id=${this.obj.ID}&uuid=${this.uuid}&desDir=${this.dirPath}`
            },
        },
        mounted() {
            let userData = localStorage.getItem("vuex");
            this.uuid = JSON.parse(userData).user.userInfo.uuid
            getJumpServerUserById({'id':this.$route.query.id}).then(response => {
                this.obj=response.data.list;
                this.doOpened()
            })
        },
        methods: {
            changeFunction() {
                if(this.isHide) {
                    this.tableData = this.tableDataHide
                } else {
                    this.tableData= this.tableDataHide.filter(x => !x.name.startsWith('.'))
                }
            },
            openDrawer(){
                this.drawer = true
                this.openJumpServerSftpLs("",'0')
            },
            openJumpServerSftpLs(name,action){
                let pwd = this.pwd.map(x => x);
                if (action === '1') {
                    pwd.push(name)
                    let path = '/' + pwd.join('/');
                    getJumpServerSftpLs({'id':this.obj.ID,'uuid':this.uuid,'dirPath':path}).then(response => {
                        if (response.code !== 500) {
                            this.tableDataHide = response.data.list;
                            if(!this.isHide) {
                                this.tableData =response.data.list;
                                this.tableData= this.tableData.filter(x => !x.name.startsWith('.'))
                            }else {
                                this.tableData =response.data.list;
                            }
                            this.pwd = pwd
                            this.pwd.map((item, index) => {
                                this.pwdCopy[index] = item
                            })
                            this.dirPath = '/' + this.pwdCopy.join('/') + name;
                        }
                    })
                } else if (action === '2') {
                    const index = this.pwd.indexOf(name);
                    pwd = pwd.splice(0, index + 1)
                    this.dirPath = '/' + pwd.join('/');
                    this.pwd =pwd
                    this.pwdCopy = pwd
                    getJumpServerSftpLs({'id':this.obj.ID,'uuid':this.uuid,'dirPath':this.dirPath}).then(response => {
                        this.tableDataHide = response.data.list;
                        if(!this.isHide) {
                            this.tableData =response.data.list;
                            this.tableData= this.tableData.filter(x => !x.name.startsWith('.'))
                        }else {
                            this.tableData =response.data.list;
                        }
                    })
                } else {
                    this.pwd =[]
                    this.pwdCopy=[]
                    pwd = []
                    this.dirPath = '/';
                    getJumpServerSftpLs({'id':this.obj.ID,'uuid':this.uuid,'dirPath':this.dirPath}).then(response => {
                        this.tableDataHide = response.data.list;
                        if(!this.isHide) {
                            this.tableData =response.data.list;
                            this.tableData= this.tableData.filter(x => !x.name.startsWith('.'))
                        }else {
                            this.tableData =response.data.list;
                        }
                    })
                }
            },
            downLoadFile(file,fileName){
                let url = "http://" + location.hostname + ":8081" + "/jump/sftp/downLoadJumServerSftpFile";
                let refUrl = `${url}?id=${this.obj.ID}&uuid=${this.uuid}&fileName=${fileName}&filePath=${file}`;
                window.location.href = refUrl
            },
            onWindowResize() {
                this.term.fit(); // it will make terminal resized.
            },
            doLink(ev, url) {
                if (ev.type === 'click') {
                    window.open(url)
                }
            },
            doClose() {
                window.removeEventListener("resize", this.onWindowResize);
                // this.term.off("resize", this.onTerminalResize);
                if (this.ws) {
                    this.ws.close()
                }
                if (this.term) {
                    this.term.dispose()
                }
                this.uuid = ""
                this.obj = {}
                this.dirPath=""
            },
            doOpened() {
                Terminal.applyAddon(fit);
                Terminal.applyAddon(webLinks);
                Terminal.applyAddon(search);
                //TODO 网页终端添加搜索功能
                this.term = new Terminal({
                    rows: 20,
                    fontSize: 18,
                    cursorBlink: true,
                    cursorStyle: 'bar',
                    bellStyle: "sound",
                });
                this.term.open(this.$refs.terminal);
                this.term.fit(); // first resizing
                this.term.webLinksInit(this.doLink);
                // term.on("resize", this.onTerminalResize);
                window.addEventListener("resize", this.onWindowResize);
                this.ws = new WebSocket(this.wsUrl);
                // this.ws.onerror = event => {
                //     this.$message.error('ssh ws failed please retry or check your auth config');
                // };
                this.ws.onclose = (ce) => {
                    this.term.setOption("cursorBlink", false);
                    if (ce.code !== 1005) {
                        this.$notify.error({
                            title: `code ${ce.code}`,
                            message: ce.reason,
                        });
                        this.doClose();
                    }
                };
                bindTerminal(this.term, this.ws, true, -1);
                bindTerminalResize(this.term, this.ws);
            },
            uploadSuccess(res) {
                if (res.code == 0) {
                    this.$message({
                        type: "success",
                        message: "上传成功",
                    });
                    getJumpServerSftpLs({'id':this.obj.ID,'uuid':this.uuid,'dirPath':this.dirPath}).then(response => {
                        this.tableDataHide = response.data.list;
                        if(!this.isHide) {
                            this.tableData =response.data.list;
                            this.tableData= this.tableData.filter(x => !x.name.startsWith('.'))
                        }else {
                            this.tableData =response.data.list;
                        }
                    })
                } else {
                    this.$message({
                        type: "warning",
                        message: res.msg,
                    });
                }
            },
            uploadError() {
                this.$message({
                    type: "error",
                    message: "上传失败",
                });
            },
        },
    }
</script>

<style scoped>
    .container {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
    }

    .header {
        height: 46px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 0 10px;
        background-color: #e6f7ff;
    }

    .terminal {
        flex: 1;
        display: flex;
        background-color: #000;
        padding-left: 5px;
    }

    .terminal > div {
        flex: 1
    }
    .drawerHeader {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 8px;
        margin-left: 15px;

    }

    ::v-deep .drawerHead  #el-drawer__title {
        margin-bottom: 15px;
        color: rgba(0, 0, 0, 0.85);
        font-size: 16px;
        line-height: 24px;
        font-weight: 500;
        border-bottom: 1px solid #e8e8e8!important;
    }
    .actions {
        display: flex;
        align-items: center;
    }
    .el-switch {
        margin-right: 20px;
    }
    .table-file {
        border: 1px solid #ccc;
        margin-left: 4px;
        border-radius: 5px;
        margin-right: 4px;
    }
</style>
